package com.oner365.test.stream;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.google.common.math.IntMath;

//几个常用stream对list的操作
public class ListStreamDemo {

  private static final Logger LOGGER = LoggerFactory.getLogger(ListStreamDemo.class);

  public static void main(String[] args) {
    System.out.println(103/4);
    // 创建数据
    List<TenderBo> list = createData();
    final Map<String, BigDecimal> deleteMap = new HashMap<>();
    list.stream().forEach(t ->{
      deleteMap.put(t.getUnloadName(), t.getMaxLimitPrice());
    });
    LOGGER.info("deleteMap size:{}",deleteMap.keySet());
    final Map<String, BigDecimal> deleteMap1 = list.stream().collect(Collectors.toMap(TenderBo::getUnloadName,TenderBo::getMaxLimitPrice ,(v1,v2)->v2));
    LOGGER.info("deleteMap size:{}",deleteMap1);
    List<List<TenderBo>> list1 = Lists.partition(list , IntMath.divide(list.size(), 10, RoundingMode.CEILING));
    LOGGER.info("list1 size:{}",list1.size());
    list1.stream().forEach(l ->{
      LOGGER.info("size:{}",l.size());
    });
   
    // 拼接字符串
    LOGGER.info("splicingListByKey:{}", splicingListByKey(list, ","));
    // 截取list
    LOGGER.info("subList:{}", subList(0, 2, list).size());
    BigDecimal gasTotal = getGasTotal(list);
    LOGGER.info("getGasTotal:{}", gasTotal);
    double gas = getAverageDailyGasSum(list);
    LOGGER.info("getGasTotal:{}", gas);
    LOGGER.info("digDecimalDivide:{}", digDecimalDivide(gasTotal, BigDecimal.valueOf(gas)));
    groupList(list).keySet().stream().forEach(key -> LOGGER.info("key:{}", key));
    groupList(list).keySet().stream().forEach(key -> LOGGER.info("key:{}", key));
    groupList(list).values().stream()
        .forEach(v -> v.stream().forEach(t -> LOGGER.info("unloadName:{}", t.getUnloadName())));
    List<String> distinctList = new ArrayList<String>();
    distinctList.add("A");
    distinctList.add("A");
    LOGGER.info("list size:{},distinct:{}", distinctList.size(), distinct(distinctList).size());
    LOGGER.info("isAllString:{}", isAllString());
    LOGGER.info("getMax:{}", getMax());
    LOGGER.info("getMin:{}", getMin());

    srotListByInteger(list);

    srotList(list);
    
    skip(2);
    subList(0,10);
    String badStrReg = "\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
    Pattern sqlPattern = Pattern.compile(badStrReg, Pattern.CASE_INSENSITIVE);
    if (sqlPattern.matcher("").find()) {
      LOGGER.error("sql注入检查：输入信息存在SQL攻击！");
      throw new RuntimeException("sql注入检查：参数含有非法攻击字符，已禁止继续访问！");
    }
  }

  // 获取最大
  // 值得注意的是返回值，返回值0或其他正整数为true，负整数为false
  public static Long getMax() {
    List<Long> list = new ArrayList<Long>();
    list.add(1l);
    list.add(2l);
    list.add(3l);
    return list.stream().max((a, b) -> a > b ? 0 : -1).get();
  }

  // 获取最小hascode
  // 字符串没做排序就是比较了下hascode
  // 值得注意的是返回值，返回值0或其他正整数为true，负整数为false
  public static String getMin() {
    List<String> list = new ArrayList<String>();
    list.add("1234");
    list.add("4532");
    list.add("sdf");
    return list.stream().max((a, b) -> a.hashCode() > b.hashCode() ? 0 : -1).get();
  }

  // 全匹配
  public static boolean isAllString() {
    Pattern pattern = Pattern.compile("\\d{1,}(,\\d{1,}){0,}");
    List<String> stringList = new ArrayList<String>();
    stringList.add("1234");
    stringList.add("sad");
    stringList.add("987");
    return stringList.stream().allMatch(s -> pattern.matcher(s).matches());
  }

  // 去重
  public static List<String> distinct(List<String> list) {
    return list.stream().distinct().collect(Collectors.toList());
  }

  // 用key做分割拼接list成字符串
  public static String splicingListByKey(List<TenderBo> list, String key) {
    return list.stream().map(TenderBo::getUnloadName).collect(Collectors.joining(key));
  }

  // 截取list
  public static List<TenderBo> subList(int start, int end, List<TenderBo> list) {
    return list.subList(start, end);
  }

  // BigDecimal 除
  // 向上取余，保留两位
  public static BigDecimal digDecimalDivide(BigDecimal dividend, BigDecimal divisor) {
    return dividend.divide(divisor, 2, RoundingMode.HALF_UP);
  }

  // PriceDecrease 乘以 AverageDailyGas 结果相加
  // BigDecimal 乘\加的操作
  // stream的map用法之一
  public static BigDecimal getGasTotal(List<TenderBo> list) {
    return list.stream().map(t -> t.getPriceDecrease().multiply(BigDecimal.valueOf(t.getAverageDailyGas())))
        .reduce(BigDecimal.ZERO, BigDecimal::add);
  }

  // 求AverageDailyGas和
  // 求和stream
  // stream map用法之一
  public static double getAverageDailyGasSum(List<TenderBo> list) {
    return list.stream().mapToDouble(TenderBo::getAverageDailyGas).sum();
  }

  // 根据unloadName分组list
  // 分组stream
  public static Map<String, List<TenderBo>> groupList(List<TenderBo> list) {
    return list.stream().collect(Collectors.groupingBy(TenderBo::getUnloadName));
  }

  // 根据bean的maxLimitPrice排序
  public static void srotListByInteger(List<TenderBo> list) {
    list.stream().sorted(Comparator.comparing(TenderBo::getMaxLimitPrice)).collect(Collectors.toList())
        .forEach(tenderBo -> LOGGER.info("maxLimitPrice 升序:{}", tenderBo.getMaxLimitPrice()));

    list.stream().sorted(Comparator.comparing(TenderBo::getMaxLimitPrice).reversed()).collect(Collectors.toList())
        .forEach(tenderBo -> LOGGER.info("maxLimitPrice 降序:{}", tenderBo.getMaxLimitPrice()));
  }

  // 根据bean的version排序(不能作为版本比较使用，因为没有按照版本比较写)
  public static void srotList(List<TenderBo> list) {
    int length = list.stream().max((a, b) -> a.getVersion().length() > b.getVersion().length() ? 0 : -1).get()
        .getVersion().length();
    LOGGER.info("length:{}", length);
    
    list.stream().map(tenderBo ->{
      tenderBo.setVersionBuild(Integer.parseInt(autoGenericCode(tenderBo.getVersion().replace(".", ""),length)));
      return tenderBo;
    }).sorted(Comparator.comparing(TenderBo::getVersionBuild)).collect(Collectors.toList())
    .forEach(tenderBo -> LOGGER.info("version 升序:{}", tenderBo.getVersion()));
    
    list.stream().map(tenderBo ->{
      tenderBo.setVersionBuild(Integer.parseInt(autoGenericCode(tenderBo.getVersion().replace(".", ""),length)));
      return tenderBo;
    }).sorted(Comparator.comparing(TenderBo::getVersionBuild).reversed()).collect(Collectors.toList())
  .forEach(tenderBo -> LOGGER.info("version 降序:{}",tenderBo.getVersion()));
   
  }
  
  //跳过
  public static void skip(int index) {
    List<String> list = Arrays.asList("apple", "banana", "orange", "pear");
    List<String> resultList = list.stream().skip(index).collect(Collectors.toList());
    resultList.stream().forEach(s->LOGGER.info("跳过后的值:{}", s));
  }
  
  //截取
  public static void subList(int begin,int end) {
    List<String> list = Arrays.asList("apple", "banana", "orange", "pear");
    List<String> resultList = list.stream().skip(begin).limit(end).collect(Collectors.toList());
    resultList.stream().forEach(s->LOGGER.info("截取的值:{}", s));
  }
  
  /**
   * 不够位数的在后面补0，保留num的长度位数字
   * 
   * @param code
   * @return
   */
  public static String autoGenericCode(String code, int num) {
    return StringUtils.rightPad(code, num, "0");
  }

  // 创建测试数据
  public static List<TenderBo> createData() {
    List<TenderBo> list = new ArrayList<>();
    list.add(new TenderBo("中文", 90, 80, 2d, "1"));
    list.add(new TenderBo("中文", 120, 100, 2d, "1.4.5"));
    list.add(new TenderBo("中文", 100, 90, 2d, "1.5.5"));
    list.add(new TenderBo("中文", 110, 100, 2d, "3.1.11"));
    list.add(new TenderBo("中文", 100, 90, 2d, "1.2.2"));
    list.add(new TenderBo("中文", 100, 90, 2d, "4.1.1"));

    list.add(new TenderBo("B", 90, 80, 1d, "2.10.1"));
    list.add(new TenderBo("B", 120, 100, 1d, "1.1.1"));
    list.add(new TenderBo("B", 100, 90, 1d, "3.1.1"));
    list.add(new TenderBo("B", 110, 100, 1d, "1.6.7"));
    list.add(new TenderBo("B", 100, 90, 1d, "1.5.1"));
    list.add(new TenderBo("B", 100, 90, 1d, "9.0.13"));

    list.add(new TenderBo("C", 90, 80, 2.5d, "1.1.12"));
    list.add(new TenderBo("C", 120, 100, 2.5, "2.1.0"));
    list.add(new TenderBo("C", 100, 90, 2.5, "2.2.10"));
    list.add(new TenderBo("C", 110, 100, 2.5, "1.2.1"));
    list.add(new TenderBo("C", 100, 90, 2.5, "1.1.3"));
    list.add(new TenderBo("C", 100, 90, 2.5, "1.10.1"));
    list.add(new TenderBo("C", 100, 90, 2.5, "1.2.1"));
    list.add(new TenderBo("C", 100, 90, 2.5, "1.0.1"));
    list.add(new TenderBo("C", 100, 90, 2.5, "1.0.1"));
    return list;
  }

  // 测试对象实体
  static class TenderBo {
    private String unloadName;
    private BigDecimal maxLimitPrice;
    private BigDecimal quotePrice;
    private BigDecimal priceDecrease;
    private BigDecimal wholeDecrease;
    private BigDecimal deliveryDecrease;
    private Double averageDailyGas;

    private String version;
    
    private int versionBuild;

    // 创建测试对象
    public TenderBo(String name, Integer a, Integer b, Double gas, String version) {
      this.setMaxLimitPrice(BigDecimal.valueOf(a));
      this.setQuotePrice(BigDecimal.valueOf(b));
      this.setUnloadName(name);
      this.setAverageDailyGas(gas);
      BigDecimal priceDecrease20 = getPriceDecreaseMath();
      this.setPriceDecrease(priceDecrease20);
      this.setVersion(version);
    }

    // 测试对象值计算
    public BigDecimal getPriceDecreaseMath() {
      return this.getMaxLimitPrice().subtract(this.getQuotePrice()).multiply(BigDecimal.valueOf(100))
          .divide(this.getMaxLimitPrice(), 2, RoundingMode.HALF_UP);

    }

    public BigDecimal getMaxLimitPrice() {
      return maxLimitPrice;
    }

    public void setMaxLimitPrice(BigDecimal maxLimitPrice) {
      this.maxLimitPrice = maxLimitPrice;
    }

    public BigDecimal getQuotePrice() {
      return quotePrice;
    }

    public void setQuotePrice(BigDecimal quotePrice) {
      this.quotePrice = quotePrice;
    }

    public BigDecimal getPriceDecrease() {
      return priceDecrease;
    }

    public void setPriceDecrease(BigDecimal priceDecrease) {
      this.priceDecrease = priceDecrease;
    }

    public BigDecimal getWholeDecrease() {
      return wholeDecrease;
    }

    public void setWholeDecrease(BigDecimal wholeDecrease) {
      this.wholeDecrease = wholeDecrease;
    }

    public BigDecimal getDeliveryDecrease() {
      return deliveryDecrease;
    }

    public void setDeliveryDecrease(BigDecimal deliveryDecrease) {
      this.deliveryDecrease = deliveryDecrease;
    }

    public Double getAverageDailyGas() {
      return averageDailyGas;
    }

    public void setAverageDailyGas(Double averageDailyGas) {
      this.averageDailyGas = averageDailyGas;
    }

    public String getUnloadName() {
      return unloadName;
    }

    public void setUnloadName(String unloadName) {
      this.unloadName = unloadName;
    }

    // 不能为空判断
    public static BigDecimal ifNull(BigDecimal value) {
      if (value != null) {
        return value;
      } else {
        return BigDecimal.ZERO;
      }
    }

    // 相加计算
    public static BigDecimal sum(BigDecimal... value) {
      BigDecimal result = BigDecimal.ZERO;
      for (BigDecimal bigDecimal : value) {
        result = result.add(ifNull(bigDecimal));
      }
      return result;
    }

    /**
     * @return the version
     */
    public String getVersion() {
      return version;
    }

    /**
     * @param version the version to set
     */
    public void setVersion(String version) {
      this.version = version;
    }

    /**
     * @return the versionBuild
     */
    public int getVersionBuild() {
      return versionBuild;
    }

    /**
     * @param versionBuild the versionBuild to set
     */
    public void setVersionBuild(int versionBuild) {
      this.versionBuild = versionBuild;
    }

  }
}
